Hi guys, today we will learn how to upload and store image mongoDB database. It is not recommended in real world projects for storing media files in database. So why do we need to learn, because we are developers 😞 . Just kidding ...
So let's start coding.
Project Github link
App Overview :
Project Structure
Following table shows the overview of Rest APIs that be exported:
MethodsUrlsActionsPOST/file/uploadupload image to databaseGET/file/:filenamestream imageDELETE/file/:filenameDelete image from databaseCreate Node.js App
$ mkdir media-upload-node-mongo$ cd media-upload-node-mongo$ npm init --yes$ npm install express mongoose dotenv multer multer-gridfs-storage gridfs-streamEnter fullscreen modeExit fullscreen modeExpress : Express is minimal and flexible Node.js web applicaton framework.Mongoose : Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js.Dotenv : It loads environment variables from a .env file.Multer : Multer is node.js middleware for handling multipart/form-data, which is primarily used for uploading files.multer-gridfs-storage : It is storage engine for multer to store uploaded files to directly to mongoDB.gridfs-stream : It provides more rebus and easier to use streams.
The package.json look like :
{ "name": "media-upload-node-mongo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": {"test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": {"dotenv": "^9.0.2","express": "^4.17.1","gridfs-stream": "^1.1.1","mongoose": "^5.12.9","multer": "^1.4.2","multer-gridfs-storage": "^4.2.0" }}Enter fullscreen modeExit fullscreen modecreate index.js file in root folder
Setup Express Web ServerIn root folder, create index.js file
require("dotenv").config();const express = require("express");const app = express();const port = process.env.PORT || 8080;app.listen(port, console.log(`Listening on port ${port}...`));Enter fullscreen modeExit fullscreen modeConfigure Environment VariablesIn root folder, create .env file
DB = "mongodb://localhost/image-upload"Enter fullscreen modeExit fullscreen modeConfigure MongoDB Database
const mongoose = require("mongoose");module.exports = async function connection() {try {const connectionParams = {useNewUrlParser: true,useCreateIndex: true,useUnifiedTopology: true,};await mongoose.connect(process.env.DB, connectionParams);console.log("connected to database");} catch (error) {console.log(error);console.log("could not connect to database");}};Enter fullscreen modeExit fullscreen modeimport db.js in index.js and call it
require("dotenv").config();const connection = require("./db");...connection();...app.listen(port, console.log(`Listening on port ${port}...`));Enter fullscreen modeExit fullscreen modeConfigure Upload MiddlewareIn root folder create middleware folder and inside that folder create upload.js file.
const multer = require("multer");const GridFsStorage = require("multer-gridfs-storage");const storage = new GridFsStorage({url: process.env.DB,options: { useNewUrlParser: true, useUnifiedTopology: true },file: (req, file) => {const match = ["image/png", "image/jpeg"];if (match.indexOf(file.mimetype) === -1) {const filename = `${Date.now()}-any-name-${file.originalname}`;return filename;}return {bucketName: "photos",filename: `${Date.now()}-any-name-${file.originalname}`,};},});module.exports = multer({ storage });Enter fullscreen modeExit fullscreen modewhat we have done here :
When user send a image we check it's a valid image type or not.We save image in database and return it.Define The Routes
Upload Route :In the root folder create routes folder and inside that folder create upload.js file.
const upload = require("../middleware/upload");const express = require("express");const router = express.Router();router.post("/upload", upload.single("file"), async (req, res) => {if (req.file === undefined) return res.send("you must select a file.");const imgUrl = `http://localhost:8080/file/${req.file.filename}`;return res.send(imgUrl);});module.exports = router;Enter fullscreen modeExit fullscreen modeimport upload.js routes in index.js use it.
require("dotenv").config();const upload = require("./routes/upload");...app.use("/file", upload);...app.listen(port, console.log(`Listening on port ${port}...`));Enter fullscreen modeExit fullscreen modeImage Stream and Delete Routes :In index.js
require("dotenv").config();const upload = require("./routes/upload");const Grid = require("gridfs-stream");const mongoose = require("mongoose");const connection = require("./db");const express = require("express");const app = express();let gfs;connection();const conn = mongoose.connection;conn.once("open", function () {gfs = Grid(conn.db, mongoose.mongo);gfs.collection("photos");});app.use("/file", upload);// media routesapp.get("/file/:filename", async (req, res) => {try {const file = await gfs.files.findOne({ filename: req.params.filename });const readStream = gfs.createReadStream(file.filename);readStream.pipe(res);} catch (error) {res.send("not found");}});app.delete("/file/:filename", async (req, res) => {try {await gfs.files.deleteOne({ filename: req.params.filename });res.send("success");} catch (error) {console.log(error);res.send("An error occured.");}});const port = process.env.PORT || 8080;app.listen(port, console.log(`Listening on port ${port}...`));Enter fullscreen modeExit fullscreen modeThat's it test APIs in postman.If you found any mistakes or making it better, let me know in comment. I hope you have learned something.